package com.dingreading.cloud.admin.service.impl;

import com.dingreading.cloud.admin.entity.DeliveryAddress;
import com.dingreading.cloud.admin.entity.OrderForm;
import com.dingreading.cloud.admin.entity.table.OrderFormTableDef;
import com.dingreading.cloud.admin.mapper.OrderFormMapper;
import com.dingreading.cloud.admin.service.OrderFormService;
import com.dingreading.cloud.common.util.*;
import com.google.common.collect.Lists;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class OrderFormServiceImpl extends BaseServiceImpl<OrderFormMapper, OrderForm, OrderFormTableDef> implements OrderFormService {

    @Override
    protected OrderFormTableDef getTable() {
        return OrderFormTableDef.orderForm;
    }

    @Resource
    private OrderFormMapper orderFormMapper;

    @Override
    public PageDto<OrderForm> pageListV2(
            PageUtil pageUtil, String keyword, Integer projectType, Integer roleType, Integer status,
            String beginDate, String endDate, String payChannelCode, Integer financeStatus, String goodsName
    ) {
        //设置其他参数
        Map<String, Object> otherParams = getQueryOrderFormMap(
                keyword, projectType, roleType, status, beginDate, endDate, payChannelCode, financeStatus, goodsName
        );

        Page<OrderForm> page = getMapper().xmlPaginate("pageListXml", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long totalRow = page.getTotalRow();
        List<OrderForm> list = page.getRecords();

        // 结果
        PageDto<OrderForm> dto = new PageDto<>();
        dto.setList(list);
        dto.setTotal(totalRow);

        return dto;
    }

    @Override
    public OrderForm getByCode(String staffUid, String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public int deleteByStaffIdAndCode(String staffUid, String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.staffUid.eq(staffUid))
                .and(table.code.eq(code))
                .and(table.status.notIn(EnumType.OrderForm.OK.getType(),
                        EnumType.OrderForm.WAIT_SEND.getType(),
                        EnumType.OrderForm.SENDING.getType(),
                        EnumType.OrderForm.REFUND.getType()));
        return getMapper().deleteByCondition(condition);
    }

    @Override
    public boolean updateAddress(String staffUid, String code, DeliveryAddress address) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.staffUid.eq(staffUid))
                .and(table.code.eq(code))
                .and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType(), EnumType.OrderForm.APPLY_BANKPAY.getType()));

        return UpdateChain.of(OrderForm.class)
                .set(table.deliveryId, address.getId())
                .set(table.name, address.getName())
                .set(table.phone, address.getPhone())
                .set(table.address, address.getProvinces() + address.getAddress())
                .where(condition)
                .update();
    }

    @Override
    public boolean cancelOrder(String staffUid, String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code))
                .and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType()));

        return UpdateChain.of(OrderForm.class)
                .set(table.status, EnumType.OrderForm.CANCEL.getType())
                .set(table.statusName, EnumType.OrderForm.CANCEL.getName())
                .where(condition)
                .update();
    }

    @Override
    public boolean revocationGiftOrder(String code, String staffUid, String staffName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.status.eq(EnumType.OrderForm.WAIT_SEND.getType()))
                .and(table.projectType.eq(EnumType.BalanceProject.GIFT_GOODS.getType()).or(table.corpUid.eq(AccountUtil.SELF_CORP_UID)));

        return UpdateChain.of(OrderForm.class)
                .set(table.status, EnumType.OrderForm.WAIT_CONFIRM.getType())
                .set(table.statusName, EnumType.OrderForm.WAIT_CONFIRM.getName())
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .where(condition)
                .update();
    }

    @Override
    public boolean confirmOrder(String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.status.eq(EnumType.OrderForm.WAIT_CONFIRM.getType()));

        int waitPayType = EnumType.OrderForm.WAIT_PAY.getType();
        String waitPayName = EnumType.OrderForm.WAIT_PAY.getName();

        return UpdateChain.of(OrderForm.class)
                .set(table.status, waitPayType)
                .set(table.statusName, waitPayName)
                .where(condition)
                .update();
    }

    @Override
    public List<Long> getOperands(Integer roleType) {
        int waitConfirmType = EnumType.OrderForm.WAIT_CONFIRM.getType();
        int waitSendType = EnumType.OrderForm.WAIT_SEND.getType();

        int selfType = EnumOperationType.SELF.getType();
        int consortiumType = EnumOperationType.CONSORTIUM.getType();
        int brandJoinType = EnumOperationType.BRAND_JOIN.getType();
        int productJoinType = EnumOperationType.PRODUCT_JOIN.getType();
        int easyProductJoinType = EnumOperationType.EASY_PRODUCT_JOIN.getType();
        int cooperationType = EnumOperationType.COOPERATION.getType();
        // 查询总数
        List<Long> list = orderFormMapper.getOperands(
                waitConfirmType, waitSendType, roleType, AccountUtil.WuJuanUid, selfType,
                consortiumType, brandJoinType, productJoinType, cooperationType, easyProductJoinType
        );
        return list;
    }


    @Override
    public void updatePayChannelCode(String staffUid, String code, String payChannelCode) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (staffUid != null)
            condition.and(table.staffUid.eq(staffUid));
        condition.and(table.code.eq(code));

        UpdateChain.of(OrderForm.class)
                .set(table.payChannelCode, payChannelCode)
                .where(condition)
                .update();
    }

    @Override
    public List<OrderForm> getNoPayUseCouponForm(String storeUid, String staffUid, Long couponStaffId, String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.staffUid.eq(staffUid))
                .and(table.couponStaffId.eq(couponStaffId))
                .and(table.status.in(EnumType.OrderForm.WAIT_CONFIRM.getType(), EnumType.OrderForm.WAIT_PAY.getType(), EnumType.OrderForm.APPLY_BANKPAY.getType()))
                .and(table.code.ne(code));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public boolean resumeOrder(String code, Integer status, String statusName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.status.eq(EnumType.OrderForm.CANCEL.getType()));
        return UpdateChain.of(OrderForm.class)
                .set(table.status, status)
                .set(table.statusName, statusName)
                .where(condition)
                .update();
    }

    @Override
    public boolean setOk(String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.status.eq(EnumType.OrderForm.WAIT_SEND.getType())
                        .or(table.status.eq(EnumType.OrderForm.SENDING.getType())));

        int okType = EnumType.OrderForm.OK.getType();
        String okName = EnumType.OrderForm.OK.getName();

        return UpdateChain.of(OrderForm.class)
                .set(table.status, okType)
                .set(table.statusName, okName)
                .where(condition)
                .update();
    }

    @Override
    public List<OrderForm> getExportList(
            String keyword, Integer projectType, Integer roleType, Integer status, String beginDate, String endDate,
            String payChannelCode, Integer financeStatus, String goodsName
    ) {
        Map<String, Object> queryOrderFormMap = getQueryOrderFormMap(
                keyword, projectType, roleType, status, beginDate, endDate, payChannelCode, financeStatus, goodsName
        );
        return orderFormMapper.getExportList(queryOrderFormMap);
    }

    @Override
    public boolean refuseBankPay(String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.payChannelCode.eq(EnumType.PayChannelCode.BANK.getType()))
                .and(table.status.eq(EnumType.OrderForm.APPLY_BANKPAY.getType()));

        int waitPayType = EnumType.OrderForm.WAIT_PAY.getType();
        String waitPayName = EnumType.OrderForm.WAIT_PAY.getName();

        return UpdateChain.of(OrderForm.class)
                .set(table.payChannelCode, null)
                .set(table.status, waitPayType)
                .set(table.statusName, waitPayName)
                .set(table.financeStatus, null)
                .set(table.financeStatusName, null)
                .where(condition)
                .update();
    }

    @Override
    public boolean revocationBankPay(String code) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.payChannelCode.eq(EnumType.PayChannelCode.BANK.getType()))
                .and(table.status.eq(EnumType.OrderForm.WAIT_SEND.getType()));

        int applyBankpayType = EnumType.OrderForm.APPLY_BANKPAY.getType();
        String applyBankpayName = EnumType.OrderForm.APPLY_BANKPAY.getName();

        return UpdateChain.of(OrderForm.class)
                .set(table.status, applyBankpayType)
                .set(table.statusName, applyBankpayName)
                .where(condition)
                .update();
    }

    @Override
    public PageDto<OrderForm> pageListXml(PageUtil pageUtil, String keyword, Integer stockOutMethod, Integer status, String goodsName) {
        int okType = EnumType.OrderForm.OK.getType();
        int waitSendType = EnumType.OrderForm.WAIT_SEND.getType();
        int sendingType = EnumType.OrderForm.SENDING.getType();

        int payedType = EnumType.ShopCart.PAYED.getType();
        int sendType = EnumType.ShopCart.SEND.getType();

        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("okType", okType);
        otherParams.put("waitSendType", waitSendType);
        otherParams.put("sendingType", sendingType);
        otherParams.put("payedType", payedType);
        otherParams.put("sendType", sendType);
        otherParams.put("keyword", keyword);
        otherParams.put("stockOutMethod", stockOutMethod);
        otherParams.put("status", status);
        otherParams.put("goodsName", goodsName);

        Page<OrderForm> page = getMapper().xmlPaginate("orderFormPageXml", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long totalRow = page.getTotalRow();
        List<OrderForm> list = page.getRecords();

        // 结果
        PageDto<OrderForm> dto = new PageDto<>();
        dto.setList(list);
        dto.setTotal(totalRow);

        return dto;
    }

    @Override
    public boolean updateFinanceStatus(String code, Integer financeStatus, String financeStatusName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.code.eq(code))
                .and(table.payChannelCode.eq(EnumType.PayChannelCode.BANK.getType()))
                .and(table.status.in(
                        EnumType.OrderForm.WAIT_SEND.getType(), EnumType.OrderForm.SENDING.getType(),
                        EnumType.OrderForm.OK.getType(), EnumType.OrderForm.APPLY_BANKPAY.getType())
                );

        return UpdateChain.of(OrderForm.class)
                .set(table.financeStatus, financeStatus)
                .set(table.financeStatusName, financeStatusName)
                .where(condition)
                .update();
    }

    @Override
    public boolean updateSaleStaff(String code, String saleStaffUid, String saleStaffName, String saleStaffPhone) {
        return UpdateChain.of(OrderForm.class)
                .set(table.saleStaffUid, saleStaffUid)
                .set(table.saleStaffName, saleStaffName)
                .set(table.saleStaffPhone, saleStaffPhone)
                .where(table.code.eq(code))
                .update();
    }


    @Override
    public List<OrderForm> listByCodes(List<String> orderCodes) {
        return getMapper().selectListByCondition(table.code.in(orderCodes));
    }

    @Override
    public List<OrderForm> makeupList() {
        QueryCondition condition = table.corpUid.ne(AccountUtil.SELF_CORP_UID)
                .and(table.projectType.eq(EnumType.BalanceProject.BUY_GOODS.getType()))
                .and(table.status.in(2, 3, 4))
                .and(table.code.isNotNull());

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition);

        return getMapper().selectListByQuery(wrapper);
    }

    /**
     * 获取商城订单的查询参数
     */
    private Map<String, Object> getQueryOrderFormMap(
            String keyword, Integer projectType, Integer roleType, Integer status, String beginDate, String endDate,
            String payChannelCode, Integer financeStatus, String goodsName
    ) {
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("keyword", keyword);
        otherParams.put("projectType", projectType);
        otherParams.put("roleType", roleType);
        otherParams.put("status", status);
        otherParams.put("goodsName", goodsName);
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate)) {
            otherParams.put("beginDate", QueryFiledUtil.appendMin00(beginDate));
            otherParams.put("endDate", QueryFiledUtil.appendMin24(endDate));
        }
        otherParams.put("payChannelCode", payChannelCode);
        otherParams.put("financeStatus", financeStatus);
        // 财务的能查看的订单状态
        otherParams.put("financeStatusList",
                Lists.newArrayList(
                        EnumType.OrderForm.WAIT_SEND.getType(), EnumType.OrderForm.SENDING.getType(), EnumType.OrderForm.OK.getType(),
                        EnumType.OrderForm.REFUND.getType(), EnumType.OrderForm.APPLY_BANKPAY.getType()
                )
        );
        // 赠品订单类型
        otherParams.put("projectTypeGive", EnumType.BalanceProject.GIFT_GOODS.getType());
        // 吴娟员工uid
        otherParams.put("wj_staffUid", AccountUtil.WuJuanUid);

        int selfType = EnumOperationType.SELF.getType();
        int consortiumType = EnumOperationType.CONSORTIUM.getType();
        int brandJoinType = EnumOperationType.BRAND_JOIN.getType();
        int productJoinType = EnumOperationType.PRODUCT_JOIN.getType();
        int easyProductJoinType = EnumOperationType.EASY_PRODUCT_JOIN.getType();
        int cooperationType = EnumOperationType.COOPERATION.getType();
        otherParams.put("selfType", selfType);
        otherParams.put("consortiumType", consortiumType);
        otherParams.put("brandJoinType", brandJoinType);
        otherParams.put("productJoinType", productJoinType);
        otherParams.put("easyProductJoinType", easyProductJoinType);
        otherParams.put("cooperationType", cooperationType);

        return otherParams;
    }


}
